import cv2
import numpy as np
import os
import matplotlib.pyplot as plt

# 读取原始图像
img0 = cv2.imread('D:\HONORShare\JisuanjiShijue\PcVision\IMT\hanzi1.jpg')

# 裁剪图像
#切掉手指和表头
height, width,_ = img0.shape
cropped_height = int(height * 0.86)
img0 = img0[height - cropped_height:height, 0:width]
#切掉图片下半干扰部分
height, width,_ = img0.shape
cropped_height = int(height * 0.95)
img0 = img0[0:cropped_height, 0:width]

# 转化为灰度图形式
img = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)

# 对图像进行二值化处理
ret, binary_img = cv2.threshold(img, 110, 5, cv2.THRESH_BINARY)  # 使用阈值将图像转换为二值图像
binary_img = np.bitwise_not(binary_img)  # 按位取反反转黑白

# 应用腐蚀操作去除噪点
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))# 创建结构元素，这里是5x5的十字形结构元素
eroded_img = cv2.erode(binary_img, element, iterations=2)

# 应用膨胀操作突出图像特征
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (4, 4))
dilated_img = cv2.dilate(eroded_img, element, iterations=3)
# 中值滤波去除小白点
dilated_img = cv2.medianBlur(dilated_img, 21)

# 应用闭运算填充闭合区域
kernel = np.ones((5, 5), np.uint8)
closed_img = cv2.morphologyEx(dilated_img, cv2.MORPH_CLOSE, kernel, iterations=20)

# Canny边缘检测
lower = 0
upper = 0
blur_img = cv2.Canny(closed_img, lower, upper)

# 文字提取轮廓
contours, _ = cv2.findContours(blur_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 设置绘图区域，分为1行7列
fig, ax = plt.subplots(1, 7, figsize=(15, 5))
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
# 显示原始图像
ax[0].imshow(img, cmap='gray')
ax[0].set_title('原图灰度图', fontsize=8)
ax[0].axis('off')

# 显示二值化后的图像
ax[1].imshow(binary_img, cmap='gray')
ax[1].set_title('全局阈值处理>>二值化图', fontsize=8)
ax[1].axis('off')

# 显示腐蚀操作后的图像
ax[2].imshow(eroded_img, cmap='gray')
ax[2].set_title('应用腐蚀操作>>去除噪点', fontsize=8)
ax[2].axis('off')

# 显示膨胀操作后的图像
ax[3].imshow(dilated_img, cmap='gray')
ax[3].set_title('应用膨胀操作>>突出图像特征>>中值滤波去除小白点', fontsize=8)
ax[3].axis('off')

# 显示闭运算后的图像
ax[4].imshow(closed_img, cmap='gray')
ax[4].set_title('应用闭运算>>填充闭合区域', fontsize=8)
ax[4].axis('off')

# 显示Canny边缘检测后的图像
ax[5].imshow(blur_img, cmap='gray')
ax[5].set_title('Canny边缘检测', fontsize=8)
ax[5].axis('off')

copy_img = img.copy()
# 将灰度图像转换为彩色图像
copy_img_color = cv2.cvtColor(copy_img, cv2.COLOR_GRAY2BGR)
# 遍历轮廓列表
os.makedirs('chars')
chars_saved = []  # 存储已保存的字符
count=1
for c in contours:
    perimeter = cv2.arcLength(c, True)
    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(img0, (x, y), (x + w, y + h), (255), 3)

    # 根据周长阈值筛选并绘制边界框
    if  perimeter > 200:
        cv2.rectangle(copy_img_color, (x, y), (x + w, y + h), (20, 255, 20), 3)

        # 提取并保存字符图像
        char_img = img0[y:y + h, x:x + w]
        # 检查该字符是否已保存过，避免重复保存
        if char_img.tostring() not in chars_saved:
            char_filename = os.path.join('chars', f'{count}.png')
            cv2.imwrite(char_filename, char_img)
            count += 1
            chars_saved.append(char_img.tostring())

# 显示绿框边缘识别后的图像
ax[6].imshow(copy_img_color)
ax[6].set_title('识别结果', fontsize=8)
ax[6].axis('off')

# 显示图形
plt.tight_layout()  # 自动调整子图布局
plt.show()
